/*
 * @文件描述:此类用于解析字符串，并将指令封装成字符串发送
 * @版本:
 * @作者:周晨阳
 * @Date:2021-09-30 09:56:20
 */

using System;
using System.Collections.Generic;
using UnityEngine;
using myConection;
using System.Text;
using static COM_CODE;
/// <summary>
/// 传输数据相关枚举
/// </summary>
public class COM_CODE
{
    /// <summary>
    /// 请求类型
    /// </summary>
    public enum REQUEST_CODE
    {
        NONE,
        SEND,//主动方发送数据,通常用于长数据传输
        REQUEST_DATA,//主动方请求被动方发送数据给主动方,通常用于请求对方发送数据
        COMMAND,//主动发请求被动方执行指令,通常用于让对方执行指令,和SEND类似，相当于发送很少数据的send
    }
    /// <summary>
    /// 传输的数据类型
    /// </summary>
    public enum TYPE_CODE
    {
        NONE,
        MOTOR_POS,
        STOP_MOTOR,
        HAND_CONTROL,
        MOTOR_RAW_CONTROL,
        SENSOR_ANGLE
    }
}
// <summary>
/// 带一个个参数的指令
/// </summary>
/// <typeparam name="T0"></typeparam>
public class RequestCommand<T0>
{

    public REQUEST_CODE r;
    public TYPE_CODE t;
    public T0 value0;
    public string callbackKey;
    public RequestCommand(REQUEST_CODE r, TYPE_CODE t, T0 value0)
    {
        this.r = r;
        this.t = t;
        this.value0 = value0;
        callbackKey = r.ToString() + t.ToString();


    }
    public RequestCommand(REQUEST_CODE r, TYPE_CODE t, T0 value0, Action<object> action)
    {
        this.r = r;
        this.t = t;
        this.value0 = value0;
        callbackKey = r.ToString() + t.ToString();

        if (!Analysis.CallbackWithOneArg.ContainsKey(callbackKey))
            Analysis.CallbackWithOneArg.Add(callbackKey, action);


    }
    public RequestCommand(REQUEST_CODE r, TYPE_CODE t, T0 value0, Action<object, object> action)
    {
        this.r = r;
        this.t = t;
        this.value0 = value0;
        callbackKey = r.ToString() + t.ToString();

        if (!Analysis.CallbackWithTwoArgs.ContainsKey(callbackKey))
            Analysis.CallbackWithTwoArgs.Add(callbackKey, action);

    }
    public RequestCommand(REQUEST_CODE r, TYPE_CODE t, T0 value0, Action<object, object, object> action)
    {
        this.r = r;
        this.t = t;
        this.value0 = value0;
        callbackKey = r.ToString() + t.ToString();


        if (!Analysis.CallbackWithThreeArgs.ContainsKey(callbackKey))
            Analysis.CallbackWithThreeArgs.Add(callbackKey, action);
    }

    public void execute()
    {
        StringBuilder str = Analysis.formatString(r, t, 1);
        str.Append("Value[0]=" + value0.ToString() + ";");
        connection.Send(connection.getWorkingSocket(), str.ToString());

    }
    /// <summary>
    /// 设置回调函数
    /// </summary>
    /// <param name="action"></param>
    public void setCallback(Action<object> action)
    {
        if (!Analysis.CallbackWithOneArg.ContainsKey(callbackKey))
            Analysis.CallbackWithOneArg.Add(callbackKey, action);

    }
    public void setCallback(Action<object, object> action)
    {
        if (!Analysis.CallbackWithTwoArgs.ContainsKey(callbackKey))
            Analysis.CallbackWithTwoArgs.Add(callbackKey, action);

    }

    public void setCallback(Action<object, object, object> action)
    {
        if (!Analysis.CallbackWithThreeArgs.ContainsKey(callbackKey))
            Analysis.CallbackWithThreeArgs.Add(callbackKey, action);

    }

}

/// <summary>
/// 带两个参数的指令
/// </summary>
/// <typeparam name="T0"></typeparam>
/// <typeparam name="T1"></typeparam>
/// <typeparam name="T2"></typeparam>
public class RequestCommand<T0, T1>
{

    public REQUEST_CODE r;
    public TYPE_CODE t;
    public T0 value0;
    public T1 value1;
    public string callbackKey;
    public RequestCommand(REQUEST_CODE r, TYPE_CODE t, T0 value0, T1 value1)
    {
        this.r = r;
        this.t = t;
        this.value0 = value0;
        this.value1 = value1;
        callbackKey = r.ToString() + t.ToString();


    }
    public RequestCommand(REQUEST_CODE r, TYPE_CODE t, T0 value0, T1 value1, Action<object> action)
    {
        this.r = r;
        this.t = t;
        this.value0 = value0;
        this.value1 = value1;
        callbackKey = r.ToString() + t.ToString();

        if (!Analysis.CallbackWithOneArg.ContainsKey(callbackKey))
            Analysis.CallbackWithOneArg.Add(callbackKey, action);


    }
    public RequestCommand(REQUEST_CODE r, TYPE_CODE t, T0 value0, T1 value1, Action<object, object> action)
    {
        this.r = r;
        this.t = t;
        this.value0 = value0;
        this.value1 = value1;
        callbackKey = r.ToString() + t.ToString();

        if (!Analysis.CallbackWithTwoArgs.ContainsKey(callbackKey))
            Analysis.CallbackWithTwoArgs.Add(callbackKey, action);

    }
    public RequestCommand(REQUEST_CODE r, TYPE_CODE t, T0 value0, T1 value1, Action<object, object, object> action)
    {
        this.r = r;
        this.t = t;
        this.value0 = value0;
        this.value1 = value1;
        callbackKey = r.ToString() + t.ToString();


        if (!Analysis.CallbackWithThreeArgs.ContainsKey(callbackKey))
            Analysis.CallbackWithThreeArgs.Add(callbackKey, action);
    }

    public void execute()
    {
        StringBuilder str = Analysis.formatString(r, t, 2);
        str.Append("Value[0]=" + value0.ToString() + ";");
        str.Append("Value[1]=" + value1.ToString() + ";");
        connection.Send(connection.getWorkingSocket(), str.ToString());

    }
    /// <summary>
    /// 设置回调函数
    /// </summary>
    /// <param name="action"></param>
    public void setCallback(Action<object> action)
    {
        if (!Analysis.CallbackWithOneArg.ContainsKey(callbackKey))
            Analysis.CallbackWithOneArg.Add(callbackKey, action);

    }
    public void setCallback(Action<object, object> action)
    {
        if (!Analysis.CallbackWithTwoArgs.ContainsKey(callbackKey))
            Analysis.CallbackWithTwoArgs.Add(callbackKey, action);

    }

    public void setCallback(Action<object, object, object> action)
    {
        if (!Analysis.CallbackWithThreeArgs.ContainsKey(callbackKey))
            Analysis.CallbackWithThreeArgs.Add(callbackKey, action);

    }


}

/// <summary>
/// 带三个参数的指令
/// </summary>
/// <typeparam name="T0"></typeparam>
/// <typeparam name="T1"></typeparam>
/// <typeparam name="T2"></typeparam>
public class RequestCommand<T0, T1, T2>
{

    public REQUEST_CODE r;
    public TYPE_CODE t;
    public T0 value0;
    public T1 value1;
    public T2 value2;
    public string callbackKey;
    public RequestCommand(REQUEST_CODE r, TYPE_CODE t, T0 value0, T1 value1, T2 value2)
    {
        this.r = r;
        this.t = t;
        this.value0 = value0;
        this.value1 = value1;
        this.value2 = value2;
        callbackKey = r.ToString() + t.ToString();


    }
    public RequestCommand(REQUEST_CODE r, TYPE_CODE t, T0 value0, T1 value1, T2 value2, Action<object> action)
    {
        this.r = r;
        this.t = t;
        this.value0 = value0;
        this.value1 = value1;
        this.value2 = value2;
        callbackKey = r.ToString() + t.ToString();

        if (!Analysis.CallbackWithOneArg.ContainsKey(callbackKey))
            Analysis.CallbackWithOneArg.Add(callbackKey, action);


    }
    public RequestCommand(REQUEST_CODE r, TYPE_CODE t, T0 value0, T1 value1, T2 value2, Action<object, object> action)
    {
        this.r = r;
        this.t = t;
        this.value0 = value0;
        this.value1 = value1;
        this.value2 = value2;
        callbackKey = r.ToString() + t.ToString();

        if (!Analysis.CallbackWithTwoArgs.ContainsKey(callbackKey))
            Analysis.CallbackWithTwoArgs.Add(callbackKey, action);

    }
    public RequestCommand(REQUEST_CODE r, TYPE_CODE t, T0 value0, T1 value1, T2 value2, Action<object, object, object> action)
    {
        this.r = r;
        this.t = t;
        this.value0 = value0;
        this.value1 = value1;
        this.value2 = value2;
        callbackKey = r.ToString() + t.ToString();


        if (!Analysis.CallbackWithThreeArgs.ContainsKey(callbackKey))
            Analysis.CallbackWithThreeArgs.Add(callbackKey, action);
    }

    /// <summary>
    /// 执行命令,相当于用socket发送对应的字符串
    /// </summary>
    public void execute()
    {
        StringBuilder str = Analysis.formatString(r, t, 3);
        str.Append("Value[0]=" + value0.ToString() + ";");
        str.Append("Value[1]=" + value1.ToString() + ";");
        str.Append("Value[2]=" + value2.ToString() + ";");
        connection.Send(connection.getWorkingSocket(), str.ToString());

    }
    /// <summary>
    /// 设置回调函数
    /// </summary>
    /// <param name="action"></param>
    public void setCallback(Action<object> action)
    {
        if (!Analysis.CallbackWithOneArg.ContainsKey(callbackKey))
            Analysis.CallbackWithOneArg.Add(callbackKey, action);

    }
    public void setCallback(Action<object, object> action)
    {
        if (!Analysis.CallbackWithTwoArgs.ContainsKey(callbackKey))
            Analysis.CallbackWithTwoArgs.Add(callbackKey, action);

    }

    public void setCallback(Action<object, object, object> action)
    {
        if (!Analysis.CallbackWithThreeArgs.ContainsKey(callbackKey))
            Analysis.CallbackWithThreeArgs.Add(callbackKey, action);

    }

}
/// <summary>
/// 处理接收请求
/// </summary>
public class InvokeCommand
{
    public REQUEST_CODE r;
    public TYPE_CODE t;
    public string callbackKey;
    public InvokeCommand(REQUEST_CODE r, TYPE_CODE t, Action<object> action)
    {
        this.r = r;
        this.t = t;
        callbackKey = r.ToString() + t.ToString();

        if (!Analysis.CallbackWithOneArg.ContainsKey(callbackKey))
            Analysis.CallbackWithOneArg.Add(callbackKey, action);


    }
    public InvokeCommand(REQUEST_CODE r, TYPE_CODE t, Action<object, object> action)
    {
        this.r = r;
        this.t = t;
        callbackKey = r.ToString() + t.ToString();

        if (!Analysis.CallbackWithTwoArgs.ContainsKey(callbackKey))
            Analysis.CallbackWithTwoArgs.Add(callbackKey, action);

    }
    public InvokeCommand(REQUEST_CODE r, TYPE_CODE t, Action<object, object, object> action)
    {
        this.r = r;
        this.t = t;
        callbackKey = r.ToString() + t.ToString();


        if (!Analysis.CallbackWithThreeArgs.ContainsKey(callbackKey))
            Analysis.CallbackWithThreeArgs.Add(callbackKey, action);
    }

}
public class Analysis : MonoBehaviour
{


    private connection connection;
    //创建3个字典，用于保存不同参数个数的action
    public static Dictionary<string, Action<object>> CallbackWithOneArg = new Dictionary<string, Action<object>>();
    public static Dictionary<string, Action<object, object>> CallbackWithTwoArgs = new Dictionary<string, Action<object, object>>();
    public static Dictionary<string, Action<object, object, object>> CallbackWithThreeArgs = new Dictionary<string, Action<object, object, object>>();

    void Awake()
    {
    }
    // Start is called before the first frame update
    void Start()
    {
        GameObject conObj = GameObject.Find("GameObject");
        connection = (connection)conObj.GetComponent(typeof(connection));

    }
    // Update is called once per frame
    void Update()
    {

    }
    /// <summary>
    /// 生成规定格式的字符串,遵循Request=1;Type=1;Conut=1;Value[0]=100;这种格式
    /// </summary>
    /// <param name="r">REQUEST_CODE</param>
    /// <param name="t">TYPE_CODE</param>
    /// <param name="count">value的数量</param>
    /// <returns></returns>
    public static StringBuilder formatString(REQUEST_CODE r, TYPE_CODE t, int count)
    {
        StringBuilder str = new StringBuilder();
        str.Append("Request=");
        str.Append((int)r);
        str.Append(";");

        str.Append("Type=");
        str.Append((int)t);
        str.Append(";");

        str.Append("Count=");
        str.Append(count.ToString());
        str.Append(";");
        return str;

    }
    /// <summary>
    /// 解析字符串并自动调用相应的回调函数或者调用本地函数
    /// </summary>
    /// <param name="s"></param>
    public static void analysisString(string s)
    {
        //Console.WriteLine("content" + s);
        //检查是否为规定格式的指令,若不是就直接退出
        if (s.IndexOf("Request=") <= -1 && s.IndexOf("Type=") <= -1 && s.IndexOf("Count=") <= -1)
        {
            return;
        }
        try
        {
            REQUEST_CODE r = REQUEST_CODE.NONE;
            TYPE_CODE typeCode = TYPE_CODE.NONE;
            int Count = 0;
            Action<object> callback1 = null;
            Action<object, object> callback2 = null;
            Action<object, object, object> callback3 = null;
            object value0, value1, value2;
            string[] args = s.Split(new char[2] { '=', ';' });
            r = (REQUEST_CODE)int.Parse(args[1]);
            typeCode = (TYPE_CODE)int.Parse(args[3]);
            string callbackKey = null;

            //根据REQUEST_CODE和TYPE_CODE创建key来寻找对应的action
            if (r == REQUEST_CODE.REQUEST_DATA)
            {
                callbackKey = REQUEST_CODE.SEND.ToString() + typeCode.ToString(); ;

            }
            else if (r == REQUEST_CODE.SEND)
            {
                callbackKey = REQUEST_CODE.REQUEST_DATA.ToString() + typeCode.ToString(); ;

            }
            else if (r == REQUEST_CODE.COMMAND)
            {
                callbackKey = REQUEST_CODE.COMMAND.ToString() + typeCode.ToString(); ;

            }
            Count = int.Parse(args[5]);

            if (CallbackWithOneArg.ContainsKey(callbackKey))
            {
                callback1 = CallbackWithOneArg[callbackKey];

            }
            if (CallbackWithTwoArgs.ContainsKey(callbackKey))
            {
                callback2 = CallbackWithTwoArgs[callbackKey];

            }
            if (CallbackWithThreeArgs.ContainsKey(callbackKey))
            {
                callback3 = CallbackWithThreeArgs[callbackKey];

            }

            if (callback1 != null)
            {
                value0 = (args[7]);
                callback1(value0);
            }
            if (callback2 != null)
            {
                value0 = (args[7]);
                value1 = (args[9]);

                callback2(value0, value1);
            }

            if (callback3 != null)
            {
                value0 = (args[7]);
                value1 = (args[9]);
                value2 = (args[11]);

                callback3(value0, value1, value2);
            }

        }
        catch (Exception ex)
        {
            Console.WriteLine(ex);
        }
    }



}
